package group2.core.database.impl;

import group2.core.database.IJpaCtrl;
import group2.core.database.NonexistentEntityException;
import group2.core.entities.*;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import javax.transaction.UserTransaction;

/**
 * Manages the database connection for Posts.
 * 
 * @author Christian
 */
public class PostJpaCtrl implements IJpaCtrl<Post> {

    // UserTransaction not used in non container (i.e. for now)
    private final UserTransaction utx;
    // Get from Database
    private final EntityManagerFactory emf;

    public PostJpaCtrl(UserTransaction utx, EntityManagerFactory emf) {
        this.utx = utx;
        this.emf = emf;
    }

    @Override
    public void create(Post t) {
        EntityManager em = getEntityManager();
        try {
            em.getTransaction().begin();
            em.persist(t);
            t.getUserClass().addPost(em.find(Post.class, t.getId()));
            em.merge(t.getUserClass());
            em.getTransaction().commit();
        } catch (Exception e) {
            Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exception caught", e);
            em.getTransaction().rollback();
        } finally {
            em.close();
        }
    }

    @Override
    public void destroy(Long id) throws NonexistentEntityException {
        EntityManager em = getEntityManager();
        try {
            em.getTransaction().begin();
            Post p = em.find(Post.class, id);
            List<Comment> deleteList = p.getComments();
            for (Comment c : deleteList) {
                c.getCommentAuthor().removeComment(c);
            }
            p.getUserClass().removePost(p);
            em.remove(p);
            em.getTransaction().commit();
        } finally {
            em.close();
        }
    }

    @Override
    public void edit(Post t) throws NonexistentEntityException, Exception {
        EntityManager em = getEntityManager();
        try {
            em.getTransaction().begin();
            em.merge(t);
            em.getTransaction().commit();
        } finally {
            em.close();
        }
    }

    @Override
    public List<Post> findEntities() {
        EntityManager em = getEntityManager();
        List<Post> list = null;

        CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery<Post> query = builder.createQuery(Post.class);
        Root<Post> p = query.from(Post.class);
        query.select(p);
        TypedQuery<Post> q = em.createQuery(query);
        list = q.getResultList();
        if (list == null) {
            list = new ArrayList();
        }
        return list;
    }

    @Override
    public List<Post> findEntities(int maxResults, int firstResult) {
        List<Post> list = findEntities();

        if (maxResults >= list.size()) {
            maxResults = list.size();
        }

        if (firstResult + maxResults > list.size()) {
            firstResult = list.size() - maxResults;
        }

        return list.subList(firstResult, firstResult + maxResults);
    }

    @Override
    public Post findEntity(Long id) {
        Post p = null;
        EntityManager em = getEntityManager();
        try {
            em.getTransaction().begin();
            p = em.find(Post.class, id);
            em.getTransaction().commit();
        } finally {
            em.close();
            return p;
        }
    }

    @Override
    public int getEntityCount() {
        return findEntities().size();
    }

    @Override
    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }
}
